package test;

import java.util.List;
import java.util.Vector;

import util.Constants;
import util.Visual;
import algorithm.RADDACL_Cluster;
import algorithm.Classification;
import algorithm.Region;
import algorithm.Region_Original;
import algorithm.SimpleClassification;
import algorithm.quartile.Region_Quartile;

/**
 * Offers different kinds of input for testing purposes
 * 
 * @author Dan Avila
 *
 */
public class Main {
	
	private Vector<Vector<Double>> inputs;
	private RADDACL_Cluster cluster;
	private Visual visual;
	List<Classification> classes = null;
	
	public Main()
	{
		reset();
	}

	public static void main(String[]args)
	{
		new Main();
	}
	
	public void reset()
	{
		Constants.instance.resetInput();
		
		System.out.println("");
		
		inputs = new Vector<Vector<Double>>();
		
		Class<? extends SimpleClassification> classification = SimpleClassification.class;
		Class<? extends Region> regionType = Region_Quartile.class;
		
		if(Constants.instance.constants.get("density").equals("Derek"))
		{
			regionType = Region_Original.class;
		}
		
		cluster = new RADDACL_Cluster(
				getData(), 
				classification,
				regionType
				);

		try {
			 classes = cluster.classifyInput();
			
		} catch (InstantiationException e) {
			
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			
			e.printStackTrace();
		}
		
		if(visual == null)	//its our first one
		{
			visual = new Visual(this);
		}
		else	//its our next one
		{
			visual.reset(this);
		}
		
		System.out.println("INPUTS: \n"+this.cluster.toString());
	}
	
	public Vector<Vector<Double>> getData()
	{
		
		for(int i = 0; i < Constants.instance.objects.size();i++)
		{	
			if(Constants.instance.objects.get(i).get(0).equals("circle"))
			{
				createCircle(i);
			}
			else if(Constants.instance.objects.get(i).get(0).equals("random"))
			{
				createRandom(i);
			}
			else
			{
				addPoint(i);
			}
		}
		
		for(Vector<Double> point: this.inputs)
		{
			for(Double dimension: point)
			{
				System.out.print(dimension + " ");
			}
			
			System.out.println();
		}
		
		return inputs;
	}
	
	public List<Classification> getPreClusters() throws InstantiationException, IllegalAccessException
	{
		return this.cluster.getClassifications();
	}
	
	public List<Classification> getFinalClusters() 
	{	
		return this.classes;
	}
	
	private void addPoint(int currentNum) 
	{
		List<Object> list = Constants.instance.objects.get(currentNum);
		
		Vector<Double> d = new Vector<Double>();
		
		for(int i = 0; i < list.size();i++)
		{
			d.add(Double.parseDouble((String)list.get(i)));
		}
		
		this.inputs.add(d);
	}

	private void createCircle(int currentNum)
	{
		int elements = Integer.parseInt((String)Constants.instance.objects.get(currentNum).get(1));
		double radius = Double.parseDouble(((String)Constants.instance.objects.get(currentNum).get(2)));
		int xcenter = Integer.parseInt((String)Constants.instance.objects.get(currentNum).get(3));
        int ycenter = Integer.parseInt((String)Constants.instance.objects.get(currentNum).get(4));
        double percentVal = Double.parseDouble(((String)Constants.instance.objects.get(currentNum).get(5)));
        
		for(int i = 0; i < elements ; i++)
		{
			Vector<Double> d = new Vector<Double>();
			
			double a = Math.random()*360;
			
			double percent = (100 - Math.random()*percentVal)/100;
			
		    d.add(new Double(radius * percent * Math.cos(a) + xcenter));
		    d.add(new Double(radius * percent * Math.sin(a) + ycenter)); 
		    
			this.inputs.add(d);
		}
	}
	
	private void createRandom(int currentNum)
	{
		int xmin = Integer.parseInt((String)Constants.instance.objects.get(currentNum).get(2));
		int ymin = Integer.parseInt((String)Constants.instance.objects.get(currentNum).get(3));
		int xmax = Integer.parseInt((String)Constants.instance.objects.get(currentNum).get(4));
		int ymax = Integer.parseInt((String)Constants.instance.objects.get(currentNum).get(5));
		
		int points = Integer.parseInt((String)Constants.instance.objects.get(currentNum).get(1));
		
		for(int i = 0; i < points; i++)
		{
			Vector<Double> d = new Vector<Double>();
			d.add(Math.random()*(xmin+xmax) - xmin);
			d.add(Math.random()*(ymin+ymax) - ymin);
			
			this.inputs.add(d);
		}
	}
}
